package start.demo01.erupt;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程协作（通信）
 * 		Condition----->Lock对象创建newCondition()
 * 			await():线程等待
 * 			signal():唤醒指定等待的线程，重新执行
 * 			signalAll():唤醒所有等待的线程
 * 
 * 创建两个线程，一个线程用于取款任务；一个用于存款任务
 * 取款任务从账户中取一笔钱，当账户中金额小于取款金额时，取款线程必须等待
 * 存款任务存入一笔钱进账户，无论存放多少钱，都应该通知等待取款的线程重新取款，当
 * @author Adan
 *
 */
public class ThreadCooperation {
	private static Account account = new Account();
	public static void main(String[] args) {
		ExecutorService service =Executors.newFixedThreadPool(2);
		service.execute(new DepositTask());
		service.execute(new DrawTask());
		service.shutdown();
	}
	private static class Account{
		private static Lock lock = new ReentrantLock();
		private static Condition newDeposit = lock.newCondition();
		private int balance = 0;

		public int getBalance() {
			return balance;
		}
		
		public void deposit(int amount) {
			lock.lock();
			try {
				balance += amount;
				System.out.println("账户中金额:" + getBalance());
				newDeposit.signalAll();
			}finally {
				lock.unlock();
			}
		}
		
		public void draw(int amount) {
			lock.lock();
			try {
				while(balance < amount) {
					System.out.println("等待存款线程存入一笔钱");
					newDeposit.await();
				}
				balance -= amount;
				System.out.println("账户中金额:" + getBalance());
			}catch (InterruptedException e) {
				e.printStackTrace();
			}finally {
				lock.unlock();
			}
		}
	}
	private static class DepositTask implements Runnable{
		@Override
		public void run() {
			while(true) {
				try {
					account.deposit((int)(Math.random() * 100));
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private static class DrawTask implements Runnable{
		@Override
		public void run() {
			while(true) {
				account.draw((int)(Math.random() * 100));
			}
		}
	}
}
